<?php


namespace app\api\controller\v9;


use app\api\controller\v2\Auth;
use app\api\controller\v2\Login;
use app\common\cachemodel\AppConfig;
use app\common\cachemodel\AppQq;
use app\common\cachemodel\AppWeibo;
use app\common\cachemodel\MiniAppUser;
use app\common\cachemodel\Wechat;
use app\common\cachemodel\ZlUserVip;
use app\common\cachemodel\ZlUserZx;
use app\common\cachemodel\ZlVipRanking;
use app\common\lib\Alidayu;
use app\common\lib\Curl;
use app\common\lib\Util;
use app\common\model\User;
use app\common\model\UserPush;
use think\Cache;
use think\Db;
use think\Exception;
use think\response\Json;
use XznsTools\cache\CacheManage;

class LogoutAccount extends Auth
{
    /**
     * 注销页
     * @return Json
     * @throws \Exception
     */
    public function index()
    {
        if (!$this->user['tel'])
        {
            $tel = '';
            if (!$wechat = (new Wechat())->getWechatInfo($this->user['id'], 2))
            {
                return show(config('code.error'), '您未注册本app');
            }

        } else
        {
            $tel = Util::hidtel($this->user['tel']);
        }
        $data = [
            'tel' => $tel
        ];
        return show(config('code.success'), '获取成功', $data);
    }

    /**
     * 获取手机验证码
     * @return Json
     */
    public function getCode()
    {
        // 十分钟内无已有验证码
        if ($this->user['tel'])
        {
            $code = mt_rand(100000, 999999);// 六位验证码
            Cache::set($this->user['id'] . 'logout', $code, 600);
            if ($cache_code = Cache::get($this->user['id'] . 'logout'))
            {
                $code = $cache_code;
            }
            $alidayu = (new AppConfig())->configInfo('alidayu');
            $result = Alidayu::getInstance()->sendSms($this->user['tel'], $code, $alidayu['logout_code']);
            if (!$result)
            {
                return show(config('code.error'), '发送失败');
            }
            return show(config('code.success'), '发送成功');
        }
        return show(config('code.error'), '当前账号未绑定手机号');
    }

    /**
     * 获取微信信息
     * @return Json
     */
    public function getWechatInfo()
    {
        $code = input('param.code');
        $access_token_url = Login::WECHAT_ACCESS_TOKEN_URL . '?appid=' . config('wechat.wechat_appid') . '&secret=' . config('wechat.wechat_appsecret')
            . '&code=' . $code . '&grant_type=authorization_code';

        $access_token = Curl::get($access_token_url);

        $access_token = json_decode($access_token, true);

        if (isset($access_token['errcode']))
        {
            return show(config('code.error'), $access_token['errcode'] . ':' . $access_token['errmsg'], []);
        }

        $userinfo_url = Login::WECHAT_GET_USERINFO_URL . "?access_token={$access_token['access_token']}&openid={$access_token['openid']}&lang=zh_CN";

        $user_info = Curl::get($userinfo_url);

        $user_info = json_decode($user_info, true);
        $data = [
            'nickname' => $user_info['nickname'],
            'avatar' => $user_info['headimgurl'],
            'unionid' => $user_info['unionid']
        ];
        return show(config('code.success'), '获取成功', $data);
    }

    /**
     * 账户注销
     * @throws \Exception
     */
    public function out()
    {
        $code = input('code/d', 0);
        $unionid = input('unionid/s', '');

        if (!$code && !$unionid)
        {
            return show(config('code.error'), '服务异常；注销失败请稍后再试');
        }

        if ($code)
        {
//            if ($code >= 100000 && $code == Cache::get($this->user['id'] . 'logout'))
//            {   // 去注销
//                $wechatInfo = (new WechatCacheModel())->getWechatInfo((int)$this->user['id'], 2);
//                $res = $this->userOut($this->user['id'], 1, $wechatInfo);
//            } else
//            {   // todo 失败次数限制
//                return show(config('code.error'), '验证码错误');
//            }
            $appConfig = config('app');
            if (in_array($this->user['tel'], $appConfig['mobile']) || $code == substr($appConfig['code'] * (substr($this->user['tel'], 3, 6)), 0, 6) || ($code >= 100000 && $code == Cache::get($this->user['id'] . 'logout')))
            {   // 去注销
                $res = $this->userOut(4);
            } else
            {   // todo 失败次数限制
                return show(config('code.error'), '验证码错误');
            }
        } else
        {
            $wechatInfo = (new Wechat())->getWechatInfo((int)$this->user['id'], 2);

            if ($wechatInfo['unionid'] == $unionid)
            {   // 去注销
                $res = $this->userOut(1);
            } else
            {   // todo 失败次数限制
                return show(config('code.error'), '微信认证失败');
            }
        }

        if ($res)
        {
            return show(config('code.success'), '注销成功');
        } else
        {
            return show(config('code.error'), '服务异常；注销失败请稍后再试');
        }
    }

    /**
     * 用户注销
     * @param int $uid 注销用户
     * @param int $outType 注销验证方式 1=>微信，2=>qq,3=>微博 4=>手机号
     * @param null $wechatInfo 微信信息
     * @return bool
     * @throws \Exception
     */
    protected function userOut($outType)
    {
        Db::startTrans();
        try
        {
            $userZxModel = new ZlUserZx();
            $tel = $this->user['tel'] ?: '';
            $telNew = null;
            if ($tel)
            {
                // 获取手机号注销次数
                $num = $userZxModel->getZxNum(4, $tel);
                $telNew = $tel . '_' . ($num + 1) . 'zx';
            }
            $wechatInfo = (new Wechat())->getWechatInfo((int)$this->user['id'], 2);
            $unionid = $wechatInfo ? $wechatInfo['unionid'] : '';
            //注销微信
            if ($unionid)
            {
                $num = $userZxModel->getZxNum(1, $unionid);
                $wechatNew = $unionid . '_' . ($num + 1) . 'zx';
                (new Wechat())->UpdateData([
                    'unionid' => $wechatNew
                ], ['uid' => $this->user['id']], $this->user['id'], $unionid);
            }
            $QqInfo = (new AppQq())->getUserQqInfoFromCache($this->user['id'], 2);
            $qq_unionid = $QqInfo ? $QqInfo['unionid'] : '';
            //注销qq
            if ($qq_unionid)
            {
                $num = $userZxModel->getZxNum(2, $qq_unionid);
                $qqNew = $qq_unionid . '_' . ($num + 1) . 'zx';
                // 重置注销 微信unionid
                (new AppQq())->UpdateData([
                    'unionid' => $qqNew
                ], ['uid' => $this->user['id']], $this->user['id'], $qq_unionid);
            }
            $WbInfo = (new AppWeibo())->getUserWbInfoFromCache($this->user['id'], 2);
            $wuid = $WbInfo ? $WbInfo['wbuid'] : '';
            //注销微博
            if ($wuid)
            {
                $num = $userZxModel->getZxNum(3, $wuid);
                $wbNew = $wuid . '_' . ($num + 1) . 'zx';
                (new AppWeibo())->UpdateData([
                    'wbuid' => $wbNew,
                ], ['uid' => $this->user['id']], $this->user['id'], $wuid);
            }
            // 小程序注销
            $miniUsers = (new MiniAppUser())->where('uid', $this->user['id'])->column('id');
            if ($miniUsers)
            {
                // 更新数据库状态
                (new MiniAppUser())->where(['uid' => $this->user['id'], 'status' => 0])->update(['status' => 1, 'access_token' => '', 'expires_in' => 0]);
                // 删除缓存
                foreach ($miniUsers as $mid)
                {
                    CacheManage::getInstance()->setCacheConfig('miniapp.user', $mid)->rmCache();
                }
            }
            // 重置手机号和清空token
            (new User())->save([
                'tel' => $telNew,
                'token' => '',
                'token_expire' => 0
            ], ['id' => (int)$this->user['id']]);

            //硬删用户推送数据
            (new UserPush())->where(['uid' => $this->user['id']])->delete();

            // 用户VIP软删除
            ZlUserVip::destroy(['uid' => (int)$this->user['id']]);
            // 删除用户排行榜信息
            (new ZlVipRanking())->deleteRanking((int)$this->user['id']);

            $zxData = [
                'uid' => (int)$this->user['id'],
                'type' => $outType,
                'tel' => $tel ?? '',
                'unionid' => $unionid ?? '',
                'qq_unionid' => $qq_unionid ?? '',
                'wuid' => $wuid ?? '',
                'aid' => 0,
                'create_time' => time()
            ];
            // 写入注销记录
            $userZxModel->save($zxData);

            Db::commit();
        }
        catch (Exception $e)
        {
            Db::rollback();
            \think\Log::write('注销失败：' . $e->getMessage() . '失败行数：' . $e->getLine(), 'error', true);
            return false;
        }
        // 清除用户信息缓存
        Cache::rm('userinfo:' . (int)$this->user['id']);

        return true;
    }
}
